﻿
Public Class stepCallbackAction
    Inherits callbackAction
    Public Const finished_step As UInt32 = maxUInt32
    Public Const initial_step As UInt32 = 0
    Private begin As _do(Of UInt32, Boolean) = Nothing
    Private check As _do(Of UInt32, Boolean) = Nothing
    Private [step] As UInt32 = initial_step

    Public Shared Function gotoStepIf(ByVal c As Boolean, ByVal [step] As UInt32) As UInt32
        Return ifoper(c, [step], finished_step)
    End Function

    Public Overrides Sub reset()
        MyBase.reset()
        [step] = 0
    End Sub

    Private Function _step() As UInt32
        Return [step]
    End Function

    Private Function _begin() As Boolean
        assert(Not begin Is Nothing)
        Return begin(_step())
    End Function

    Private Function passed(ByVal c As Boolean) As Boolean
        Return c = check_pass AndAlso [step] <> finished_step
    End Function

    Private Function _check() As Boolean
        assert(Not check Is Nothing)
        Dim c As Boolean = False
        Dim b As Boolean = False
        Do
            c = check([step])
            If passed(c) Then
                b = _begin()
                If Not b Then
                    raiseError(errorHandle.errorType.warning,
                               "action " + callstack() + ":begin[" + Convert.ToString([step]) + "] failed.")
                    Return check_pass
                End If
            End If
        Loop Until Not passed(c)
        Return c
    End Function

    Private Shared Function defaultFailureAction() As void(Of UInt32)
        Return Sub(ByRef s As UInt32)
                   s = finished_step
               End Sub
    End Function

    Public Overloads Shared Function action_check(ByVal lastAction As callbackAction,
                                                  ByVal thisAction As _do(Of UInt32, Boolean),
                                                  ByVal failureAction As void(Of UInt32),
                                                  ByRef [step] As UInt32) As Boolean
        Dim s As UInt32 = [step]
        Dim this2 As _do(Of Boolean) =
            Function() As Boolean
                Return thisAction Is Nothing OrElse do_(thisAction, s, False)
            End Function
        Dim failure2 As void =
            Sub()
                void_(failureAction, s)
            End Sub
        Dim r As Boolean = action_check(lastAction, this2, failure2)()
        [step] = s
        Return r
    End Function

    Public Overloads Shared Function action_check(ByVal lastAction As callbackAction,
                                                  ByVal thisAction As _do(Of UInt32, Boolean),
                                                  ByRef [step] As UInt32) As Boolean
        Return action_check(lastAction, thisAction, defaultFailureAction(), [step])
    End Function

    Public Overloads Shared Function action_check(ByVal lastAction As callbackAction,
                                                  ByVal thisAction As void(Of UInt32),
                                                  ByVal failureAction As void(Of UInt32),
                                                  ByRef [step] As UInt32) As Boolean
        Dim this2 As _do(Of UInt32, Boolean) =
            Function(ByRef s As UInt32) As Boolean
                void_(thisAction, s)
                Return True
            End Function
        Return action_check(lastAction, this2, failureAction, [step])
    End Function

    Public Overloads Shared Function action_check(ByVal lastAction As callbackAction,
                                                  ByVal thisAction As void(Of UInt32),
                                                  ByRef [step] As UInt32) As Boolean
        Return action_check(lastAction, thisAction, defaultFailureAction(), [step])
    End Function

    <Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
    Public Sub New(Optional ByVal begin As _do(Of UInt32, Boolean) = Nothing,
                   Optional ByVal check As _do(Of UInt32, Boolean) = Nothing,
                   Optional ByVal [end] As _do(Of Boolean) = Nothing,
                   Optional ByVal timeoutticks As Int64 = npos)
        Me.begin = begin
        Me.check = check
        MyBase.ctor(ifoper(Of _do(Of Boolean))(begin Is Nothing, Nothing, AddressOf _begin),
                    ifoper(Of _do(Of Boolean))(check Is Nothing, Nothing, AddressOf _check),
                    [end], timeoutticks, 1)
    End Sub
End Class
